package gin

import (
	authpb "e-commerce/services/auth-service/api/pb"
	"e-commerce/services/inventory-service/internal/service"
	"fmt"
	"net/http"
	"os"

	"github.com/gin-gonic/gin"
	"go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc"
	"google.golang.org/grpc"
	"google.golang.org/grpc/credentials/insecure"
	"gopkg.in/yaml.v3"
)

type InventoryHandler struct {
	InventoryService *service.InventoryService
	AuthClient       *AuthClient
}

type AuthClient struct {
	client authpb.AuthServiceClient
	conn   *grpc.ClientConn
}

type Config struct {
	AuthService auth_service `yaml:"auth_service"`
}

type auth_service struct {
	Addr string `yaml:"addr"`
}

func NewAuthClient(configPath string) (*AuthClient, error) {
	var config Config
	yamlFile, err := os.ReadFile(configPath)
	if err != nil {
		return nil, err
	}
	err = yaml.Unmarshal(yamlFile, &config)
	if err != nil {
		return nil, err
	}
	conn, err := grpc.NewClient(
		config.AuthService.Addr,
		grpc.WithTransportCredentials(insecure.NewCredentials()),
		grpc.WithStatsHandler(otelgrpc.NewClientHandler()),
	)
	if err != nil {
		return nil, err
	}

	return &AuthClient{
		client: authpb.NewAuthServiceClient(conn),
		conn:   conn,
	}, nil
}

func NewInventoryHandler(configPath string) (*InventoryHandler, error) {
	inventoryService := service.NewInventoryService(configPath)
	authClient, err := NewAuthClient(configPath)
	if err != nil {
		return nil, err
	}
	return &InventoryHandler{
		InventoryService: inventoryService,
		AuthClient:       authClient,
	}, nil
}

type stock struct {
	ProductID string `json:"product_id"`
	Quantity  int32  `json:"quantity"`
}

func (h *InventoryHandler) CreateStock(c *gin.Context) {
	var stock stock
	c.ShouldBindJSON(&stock)
	fmt.Println(stock)
	err := h.InventoryService.CreateStock(stock.ProductID, stock.Quantity)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}
	c.JSON(http.StatusOK, gin.H{"message": "Stock created successfully"})
}

func (h *InventoryHandler) Middleware() gin.HandlerFunc {
	return func(c *gin.Context) {
		token := c.GetHeader("Authorization")
		if token == "" {
			c.JSON(http.StatusUnauthorized, gin.H{"error": "Unauthorized"})
			c.Abort()
			return
		}
		response, err := h.AuthClient.client.ValidateToken(c.Request.Context(), &authpb.ValidateTokenRequest{Token: token})
		if err != nil {
			c.JSON(http.StatusUnauthorized, gin.H{"error": "Unauthorized"})
			c.Abort()
			return
		}
		if response.Valid {
			c.Next()
		} else {
			c.JSON(http.StatusUnauthorized, gin.H{"error": "Unauthorized"})
			c.Abort()
			return
		}
	}
}
